package battleroom;

import com.bulletphysics.collision.shapes.CollisionShape;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.asset.AssetManager;
import com.jme3.bounding.BoundingVolume;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.util.TangentBinormalGenerator;
import java.util.Random;
import jme3tools.optimize.GeometryBatchFactory;

/**
 *
 * @author adam & zach
 */
public class LevelState extends AbstractAppState{
    private Main mapp;
    private Node levelRoot = new Node("levelRoot");
    int x,y,z,s;
    public int numTargets = 0;

    @Override
    public void initialize(AppStateManager stateManager, Application app) {
      super.initialize(stateManager, app); 
      this.mapp = (Main)app;          // cast to a more specific class
       
      
      //I sincerly apologize for the following lines
      //^^ This is actually not a terrible way to do this..
      for(int i=0;i<75;i++)
      {
          Random ran = new Random();
          
          x=ran.nextInt(500);
          y=ran.nextInt(500);
          z=ran.nextInt(500);
          
          //This for-while segment checks to see if a cube is currently existing in space, if it does exist, then regenerate the numbers.
             for(int j=0;j<i;j++)
             {
                   while(((levelRoot.getChild(j).getLocalTranslation().x+50f) >= x && (levelRoot.getChild(j).getLocalTranslation().x-50f) < x )||
                         ((levelRoot.getChild(j).getLocalTranslation().y+50f) >= y && (levelRoot.getChild(j).getLocalTranslation().y-50f) < y )||
                         ((levelRoot.getChild(j).getLocalTranslation().z+50f) >= z && (levelRoot.getChild(j).getLocalTranslation().z-50f) < z))
                            {
                                x=ran.nextInt(500);
                                y=ran.nextInt(500);
                                z=ran.nextInt(500);
                            }
             }
             
        s=ran.nextInt(10)+ (int)PlayerState.PlayerHeight * 2;
        Vector3f temp = new Vector3f(x,y,z);    //used for generating a position(0-500,0-500,0-500)
        
        float chance = .3f;
        if(ran.nextFloat() <= chance)
        {
            //Generate a target within 50 units of ~20% of stars
            TargetControl target = new TargetControl(mapp, getRootNode(), PlayerState.PlayerWidth*2, PlayerState.PlayerHeight*2, PlayerState.PlayerWidth*2);
            float mult = 1;
            if(ran.nextFloat() < .5f)
                mult = -1;
            Vector3f targetPos = new Vector3f(x+(ran.nextFloat()*(50-s)*mult)+(s*mult), y+(ran.nextFloat()*(50-s)*mult)+(s*mult), z+(ran.nextFloat()*(50-s)*mult)+(s*mult));
            
            Box targetMesh = new Box(PlayerState.PlayerWidth*2, PlayerState.PlayerHeight*2, PlayerState.PlayerWidth*2);
            Geometry targetGeom = new Geometry("target", targetMesh);
            targetGeom.setMaterial(mapp.defaultMatRed);
            targetGeom.setLocalTranslation(targetPos);
            targetGeom.addControl(target);
            
            getRootNode().attachChild(targetGeom);
            numTargets++;
        }
    
        StarControl testStar = new StarControl(s);
        Box box1 = new Box(Vector3f.ZERO,s,s,s);        
        Geometry star = new Geometry("star", box1 );
        RigidBodyControl starControl = new RigidBodyControl(new BoxCollisionShape(
               new Vector3f(s, s, s)));
        TangentBinormalGenerator.generate(box1);
        Material mat1 = new Material(app.getAssetManager(), 
                                        "MatDefs/Lighting.j3md"); //
        mat1.setColor("Specular", ColorRGBA.White);
        mat1.setTexture("DiffuseMap", app.getAssetManager().loadTexture("Textures/stars/star_01.png"));
        mat1.setTexture("NormalMap", app.getAssetManager().loadTexture("Textures/stars/star_01_norm.png"));
        mat1.setBoolean("m_UseMaterialColors", true);
        mat1.setColor("m_Ambient",  ColorRGBA.Gray);
        mat1.setColor("m_Diffuse",  ColorRGBA.Gray);
        mat1.setColor("m_Specular", ColorRGBA.White);
        mat1.setFloat("Shininess", 10f);
        star.setMaterial(mat1);

        star.addControl(testStar);
        starControl.setMass(162f);
        starControl.setFriction(100f);
        starControl.setKinematic(true);
        starControl.setCollisionGroup(PhysicsCollisionObject.COLLISION_GROUP_03);
        starControl.setCollideWithGroups(PhysicsCollisionObject.COLLISION_GROUP_01 | PhysicsCollisionObject.COLLISION_GROUP_02);        
        star.addControl(starControl);
        levelRoot.attachChild(star);

        star.setLocalTranslation(new Vector3f(x,y,z));
        app.getStateManager().getState(BulletAppState.class).getPhysicsSpace().add(starControl); 
        generateLevelBoundaries();
      }
      
      this.mapp.getRootNode().attachChild(levelRoot);

   }
    
    public Node getRootNode()
    {
        return levelRoot;
    }
    
   @Override
    public void cleanup() {
      super.cleanup();
    }
 
    @Override
    public void setEnabled(boolean enabled) {
      // Pause and unpause
      super.setEnabled(enabled);
    }
    @Override
    public void update(float tpf) {
    }
    
    public void generateLevelBoundaries()
    {
        RigidBodyControl levelControl = new RigidBodyControl(new BoxCollisionShape( new Vector3f(550f, 550f, 1f)));        
        Material mat1 = new Material(mapp.getAssetManager(),"Common/MatDefs/Light/Lighting.j3md");
        mat1.setColor("Specular", ColorRGBA.White);
        mat1.setTexture("DiffuseMap", mapp.getAssetManager().loadTexture("Textures/stars/star_01.png"));
        mat1.setTexture("NormalMap", mapp.getAssetManager().loadTexture("Textures/stars/star_01_norm.png"));
        mat1.setBoolean("m_UseMaterialColors", true);
        mat1.setColor("m_Ambient",  ColorRGBA.Gray);
        mat1.setColor("m_Diffuse",  ColorRGBA.Gray);
        mat1.setColor("m_Specular", ColorRGBA.White);
        mat1.setFloat("Shininess", 5f);

        Box levelBox = new Box(Vector3f.ZERO, 550f,550f,1f);
        Geometry levelGeom = new Geometry("wall", levelBox);
        levelGeom.setLocalTranslation(225f,225f,0f);
        levelGeom.addControl(levelControl);
        levelGeom.setMaterial(mat1);
        levelRoot.attachChild(levelGeom);
        levelControl.setKinematic(true);
        levelControl.setCollisionGroup(PhysicsCollisionObject.COLLISION_GROUP_03);
        levelControl.setCollideWithGroups(PhysicsCollisionObject.COLLISION_GROUP_01 | PhysicsCollisionObject.COLLISION_GROUP_02);
        
        RigidBodyControl levelControl2 = new RigidBodyControl(new BoxCollisionShape( new Vector3f(550f, 550f, 1f)));
        Box levelBox2 = new Box(Vector3f.ZERO,550f,550f,1f);        
        Geometry  levelGeom2 = new Geometry("wall2", levelBox2 );
        levelGeom2.setLocalTranslation(225f,250f,500f);
        levelGeom2.addControl(levelControl2);
        levelGeom2.setMaterial(mat1);
        levelRoot.attachChild(levelGeom2);
        levelControl2.setKinematic(true);
        levelControl2.setCollisionGroup(PhysicsCollisionObject.COLLISION_GROUP_03);
        levelControl2.setCollideWithGroups(PhysicsCollisionObject.COLLISION_GROUP_01 | PhysicsCollisionObject.COLLISION_GROUP_02);
        
        RigidBodyControl levelControl3 = new RigidBodyControl(new BoxCollisionShape( new Vector3f(600f, 10f, 600f)));
        Box levelBox3 = new Box(Vector3f.ZERO,600f,10f,600f);        
        Geometry  levelGeom3 = new Geometry("wall3", levelBox3 );
        levelGeom3.setLocalTranslation(225f,-15f,270f);
        levelGeom3.addControl(levelControl3);
        levelGeom3.setMaterial(mat1);
        levelRoot.attachChild(levelGeom3);
        levelControl3.setKinematic(true);
        levelControl3.setCollisionGroup(PhysicsCollisionObject.COLLISION_GROUP_03);
        levelControl3.setCollideWithGroups(PhysicsCollisionObject.COLLISION_GROUP_01 | PhysicsCollisionObject.COLLISION_GROUP_02);

        RigidBodyControl levelControl4 = new RigidBodyControl(new BoxCollisionShape( new Vector3f(600f, 10f, 600f)));
        Box levelBox4 = new Box(Vector3f.ZERO,600f,10f,600f);        
        Geometry  levelGeom4 = new Geometry("wall4", levelBox4 );
        levelGeom4.setLocalTranslation(225f,525f,270f);
        levelGeom4.addControl(levelControl4);
        levelGeom4.setMaterial(mat1);
        levelRoot.attachChild(levelGeom4);
        levelControl4.setKinematic(true);
        levelControl4.setCollisionGroup(PhysicsCollisionObject.COLLISION_GROUP_03);
        levelControl4.setCollideWithGroups(PhysicsCollisionObject.COLLISION_GROUP_01 | PhysicsCollisionObject.COLLISION_GROUP_02);
        
        
        RigidBodyControl levelControl5 = new RigidBodyControl(new BoxCollisionShape(new Vector3f(10f, 550f, 600f)));
        Box levelBox5 = new Box(Vector3f.ZERO,10f,550f,600f);        
        Geometry  levelGeom5 = new Geometry("wall5", levelBox5 );
         Material mat2 = new Material(mapp.getAssetManager(), 
                                        "Common/MatDefs/Misc/Unshaded.j3md");
        mat2.setColor("Color", ColorRGBA.Blue);
        levelGeom5.setLocalTranslation(-100f,0f,0f);
        levelGeom5.addControl(levelControl5);
        levelGeom5.setMaterial(mat1);
        levelRoot.attachChild(levelGeom5);
        levelControl5.setKinematic(true);
        levelControl5.setCollisionGroup(PhysicsCollisionObject.COLLISION_GROUP_03);
        levelControl5.setCollideWithGroups(PhysicsCollisionObject.COLLISION_GROUP_01 | PhysicsCollisionObject.COLLISION_GROUP_02);
        

        RigidBodyControl levelControl6 = new RigidBodyControl(new BoxCollisionShape(new Vector3f(10f, 550f, 600f)));
        Box levelBox6 = new Box(Vector3f.ZERO,10f,550f,600f);        
        Geometry  levelGeom6 = new Geometry("wall6", levelBox6 );
        levelGeom6.setLocalTranslation(600f,0f,0f);
        levelGeom6.addControl(levelControl6);
        levelGeom6.setMaterial(mat1);
        levelRoot.attachChild(levelGeom6);
        levelControl6.setKinematic(true);
        levelControl6.setCollisionGroup(PhysicsCollisionObject.COLLISION_GROUP_03);
        levelControl6.setCollideWithGroups(PhysicsCollisionObject.COLLISION_GROUP_01 | PhysicsCollisionObject.COLLISION_GROUP_02);
        
        
        mapp.getStateManager().getState(BulletAppState.class).getPhysicsSpace().add(levelControl);
        mapp.getStateManager().getState(BulletAppState.class).getPhysicsSpace().add(levelControl2);
        mapp.getStateManager().getState(BulletAppState.class).getPhysicsSpace().add(levelControl3);
        mapp.getStateManager().getState(BulletAppState.class).getPhysicsSpace().add(levelControl4);
        mapp.getStateManager().getState(BulletAppState.class).getPhysicsSpace().add(levelControl5);
        mapp.getStateManager().getState(BulletAppState.class).getPhysicsSpace().add(levelControl6);
        
        
    }

}
